<?php defined('SYSPATH') or die('No direct script access.');

/**
 * Vimeo Service Driver Library
 * http://www.vimeo.com/api
 *
 * $Id$
 *
 * @package		Service Module
 * @author		Alex Sancho
 * @copyright	(c) 2008 Alex Sancho
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *	  notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *	  notice, this list of conditions and the following disclaimer in the
 *	  documentation and/or other materials provided with the distribution.
 * 3. Neither the name of copyright holders nor the names of its
 *	  contributors may be used to endorse or promote products derived
 *	  from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.	IN NO EVENT SHALL COPYRIGHT HOLDERS OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

class Service_Vimeo_Driver extends Service_Driver 
{
	protected $api_url = "www.vimeo.com/api/rest/?";
	protected $api_key = null;
	protected $token = null;
	protected $secret = null;

	/**
	 *	__construct
	 * 
	 * @param array $config
	 * @return void
	 * @access public
	 * 
	 */
	public function __construct($config = array())
	{
		$config += Kohana::config('service.vimeo');
		
		foreach($config as $key => $val)
			$this->$key = $val;
	}

	/**
	 * get_list
	 * 
	 * @param string $user_id
	 * @param integer $page
	 * @param integer $per_page
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function get_list($user_id, $page = '', $per_page = '') 
	{
		$params = array
		(
			'user_id'	=> $user_id,
			'per_page'	=> $per_page,
			'page'		=> $page
		);

		$this->api_call('vimeo.videos.getList', $params);
		return $this->response->videos;
	}

	/**
	 * get_uploaded_list
	 * 
	 * @param string $user_id
	 * @param integer $page
	 * @param integer $per_page
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function get_uploaded_list($user_id, $page = '', $per_page = '') 
	{
		$params = array
		(
			'user_id'	=> $user_id,
			'per_page'	=> $per_page,
			'page'		=> $page
		);

		$this->api_call('vimeo.videos.getUploadedList', $params);
		return $this->response->videos;
	}

	/**
	 * get_appears_in_list
	 * 
	 * @param string $user_id
	 * @param integer $page
	 * @param integer $per_page
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function get_appears_in_list($user_id, $page = '', $per_page = '') 
	{
		$params = array
		(
			'user_id'	=> $user_id,
			'per_page'	=> $per_page,
			'page'		=> $page
		);

		$this->api_call('vimeo.videos.getAppearsInList', $params);
		return $this->response->videos;
	}

	/**
	 * get_subscriptions_list
	 * 
	 * @param string $user_id
	 * @param integer $page
	 * @param integer $per_page
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function get_subscriptions_list($user_id, $page = '', $per_page = '') 
	{
		$params = array
		(
			'user_id'	=> $user_id,
			'per_page'	=> $per_page,
			'page'		=> $page
		);

		$this->api_call('vimeo.videos.getSubscriptionsList', $params);
		return $this->response->videos;
	}

	/**
	 * get_list_by_tag
	 * 
	 * @param string $tag
	 * @param string $user_id
	 * @param integer $page
	 * @param integer $per_page
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function get_list_by_tag($tag, $user_id, $page = '', $per_page = '') 
	{
		$params = array
		(
			'tag'		=> $tag,
			'user_id'	=> $user_id,
			'per_page'	=> $per_page,
			'page'		=> $page
		);

		$this->api_call('vimeo.videos.getListByTag', $params);
		return $this->response->videos;
	}

	/**
	 * get_like_list
	 * 
	 * @param string $user_id
	 * @param integer $page
	 * @param integer $per_page
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function get_like_list($user_id, $page = '', $per_page = '') 
	{
		$params = array
		(
			'user_id'	=> $user_id,
			'per_page'	=> $per_page,
			'page'		=> $page
		);

		$this->api_call('vimeo.videos.getLikeList', $params);
		return $this->response->videos;
	}

	/**
	 * get_video_contacts_list
	 * 
	 * @param string $user_id
	 * @param integer $page
	 * @param integer $per_page
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function get_video_contacts_list($user_id, $page = '', $per_page = '') 
	{
		$params = array
		(
			'user_id'	=> $user_id,
			'per_page'	=> $per_page,
			'page'		=> $page
		);

		$this->api_call('vimeo.videos.getContactsList', $params);
		return $this->response->videos;
	}

	/**
	 * get_contacts_like_list
	 * 
	 * @param string $user_id
	 * @param integer $page
	 * @param integer $per_page
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function get_contacts_like_list($user_id, $page = '', $per_page = '') 
	{
		$params = array
		(
			'user_id'	=> $user_id,
			'per_page'	=> $per_page,
			'page'		=> $page
		);

		$this->api_call('vimeo.videos.getContactsLikeList', $params);
		return $this->response->videos;
	}

	/**
	 * search
	 * 
	 * @param string $query
	 * @param string $user_id
	 * @param boolean $contacts_only
	 * @param integer $per_page
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function search($query, $user_id = '', $contacts_only = false, $per_page = '') 
	{
		if ( (bool) $contacts_only and $user_id == '')
			throw new Kohana_User_Exception('Vimeo Driver', Kohana::lang('service.missing_vimeo_uid'));
		
		$params = array
		(
			'query'			=> $query,
			'user_id'		=> $user_id,
			'contacts_only' => $contacts_only,
			'per_page'		=> $per_page
		);

		$this->api_call('vimeo.videos.search', $params);
		return $this->response->videos;
	}

	/**
	 * get_video_info
	 * 
	 * @param integer $video_id
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function get_video_info($video_id)
	{
		$this->api_call('vimeo.videos.getInfo', array('video_id' => $video_id));
		return $this->response->video;
	}

	/**
	 * delete
	 * 
	 * @param integer $video_id
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function delete($video_id) 
	{
		$this->auth('delete')->api_call('vimeo.videos.delet', array('video_id' => $video_id), true);
		return $this->response->rsp;
	}

	/**
	 * get_thumbnail_url
	 * 
	 * @param integer $video_id
	 * @param integer $size
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function get_thumbnail_url($video_id, $size)
	{
		$params = array
		(
			'video_id'	=> $video_id,
			'size'		=> $size
		);
		
		$this->api_call('vimeo.videos.getThumbnailUrl', $params);
		return $this->response->thumbnail;
	}

	/**
	 * set_title
	 * 
	 * @param integer $video_id
	 * @param string $title
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function set_title($video_id, $title)
	{
		$params = array
		(
			'video_id'	=> $video_id,
			'title'		=> $title
		);
		
		$this->auth('write')->api_call('vimeo.videos.setTitle', $params, true);
		return $this->response->rsp;
	}

	/**
	 * set_caption
	 * 
	 * @param integer $video_id
	 * @param string $caption
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function set_caption($video_id, $caption)
	{
		$params = array
		(
			'video_id'	=> $video_id,
			'caption'	=> $caption
		);
		
		$this->auth('write')->api_call('vimeo.videos.setCaption', $params, true);
		return $this->response->rsp;
	}

	/**
	 * set_favorite
	 * 
	 * @param integer $video_id
	 * @param boolean $favorite
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function set_favorite($video_id, $favorite = false)
	{
		$params = array
		(
			'video_id'	=> $video_id,
			'favorite'	=> $favorite
		);
		
		$this->auth('write')->api_call('vimeo.videos.setFavorite', $params, true);
		return $this->response->rsp;
	}

	/**
	 * add_tags
	 * 
	 * @param integer $video_id
	 * @param mixed $tags
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function add_tags($video_id, $tags)
	{
		$params = array
		(
			'video_id'	=> $video_id,
			'tags'		=> self::implode($tags)
		);
		
		$this->auth('write')->api_call('vimeo.videos.addTags', $params, true);
		return $this->response->rsp;
	}

	/**
	 * remove_tag
	 * 
	 * @param integer $video_id
	 * @param string $tag_id
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function remove_tag($video_id, $tag_id)
	{
		$params = array
		(
			'video_id'	=> $video_id,
			'tag_id'	=> $tag_id
		);
		
		$this->auth('write')->api_call('vimeo.videos.removeTag', $params, true);
		return $this->response->rsp;
	}

	/**
	 * clear_tags
	 * 
	 * @param integer $video_id
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function clear_tags($video_id)
	{
		$this->auth('write')->api_call('vimeo.videos.clearTags', array('video_id' => $video_id), true);
		return $this->response->rsp;
	}

	/**
	 * add_cast
	 * 
	 * @param integer $video_id
	 * @param string $user
	 * @param string $role
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function add_cast($video_id, $user, $role)
	{
		$params = array
		(
			'video_id'	=> $video_id,
			'user'		=> $user,
			'role'		=> $role
		);
		
		$this->auth('write')->api_call('vimeo.videos.addCast', $params, true);
		return $this->response->rsp;
	}

	/**
	 * get_cast
	 * 
	 * @param integer $video_id
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function get_cast($video_id)
	{
		$this->api_call('vimeo.videos.getCast', array('video_id' => $video_id));
		return $this->response->cast;
	}

	/**
	 * remove_cast
	 * 
	 * @param integer $video_id
	 * @param string $user
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function remove_cast($video_id, $user)
	{
		$params = array
		(
			'video_id'	=> $video_id,
			'user'		=> $user
		);
		
		$this->auth('write')->api_call('vimeo.videos.removeCast', $params, true);
		return $this->response->rsp;
	}

	/**
	 * set_privacy
	 * 
	 * @param integer $video_id
	 * @param string $privacy
	 * @param mixed $users
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function set_privacy($video_id, $privacy, $users = '')
	{
		$params = array
		(
			'video_id'	=> $video_id,
			'privacy'	=> $privacy,
			'user'		=> self::implode($users)
		);
		
		$this->auth('write')->api_call('vimeo.videos.setPrivacy', $params, true);
		return $this->response->rsp;
	}

	/**
	 * get_comments_list
	 * 
	 * @param integer $video_id
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function get_comments_list($video_id)
	{
		$this->api_call('vimeo.videos.comments.getList', array('video_id' => $video_id));
		return $this->response->comments;
	}

	/**
	 * add_comment
	 * 
	 * @param integer $video_id
	 * @param string $comment_text
	 * @param integer $reply_to_comment_id
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function add_comment($video_id, $comment_text, $reply_to_comment_id = '')
	{
		$params = array
		(
			'video_id'				=> $video_id,
			'comment_text'			=> $comment_text,
			'reply_to_comment_id'	=> $reply_to_comment_id
		);
		
		$this->auth('write')->api_call('vimeo.videos.comments.addComment', $params, true);
		return $this->response->comment;
	}

	/**
	 * delete_comment
	 * 
	 * @param integer $video_id
	 * @param integer $comment_id
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function delete_comment($video_id, $comment_id)
	{
		$params = array
		(
			'video_id'		=> $video_id,
			'comment_id'	=> $comment_id
		);
		
		$this->auth('write')->api_call('vimeo.videos.comments.deleteComment', $params, true);
		return $this->response->rsp;
	}

	/**
	 * edit_comment
	 * 
	 * @param integer $video_id
	 * @param integer $comment_id
	 * @param string $comment_text
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function edit_comment($video_id, $comment_id, $comment_text)
	{
		$params = array
		(
			'video_id'		=> $video_id,
			'comment_id'	=> $comment_id,
			'comment_text'	=> $comment_text
		);
		
		$this->auth('write')->api_call('vimeo.videos.comments.editComment', $params, true);
		return $this->response->rsp;
	}

	/**
	 * find_people_by_username
	 * 
	 * @param string $username
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function find_people_by_username($username)
	{
		$this->api_call('vimeo.people.findByUserName', array('username' => $username));
		return $this->response->user;
	}

	/**
	 * find_people_by_email
	 * 
	 * @param string $email
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function find_people_by_email($email)
	{
		$this->api_call('vimeo.people.findByEmail', array('find_email' => $email));
		return $this->response->user;
	}

	/**
	 * get_people_info
	 * 
	 * @param string $user_id
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function get_people_info($user_id)
	{
		$this->api_call('vimeo.people.getInfo', array('user_id' => $user_id));
		return $this->response->person;
	}

	/**
	 * get_people_portrait_url
	 * 
	 * @param string $user
	 * @param integer $size
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function get_people_portrait_url($user, $size)
	{
		$params = array
		(
			'user'	=> $user,
			'size'	=> $size
		);
		
		$this->api_call('vimeo.people.getPortraitUrl', $params);
		return $this->response->portrait;
	}

	/**
	 * add_contact
	 * 
	 * @param string $user
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function add_contact($user)
	{
		$this->auth('write')->api_call('vimeo.people.addContact', array('user' => $user), true);
		return $this->reponse->rsp;
	}

	/**
	 * remove_contact
	 * 
	 * @param string $user
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function remove_contact($user)
	{
		$this->auth('write')->api_call('vimeo.people.removeContact', array('user' => $user), true);
		return $this->reponse->rsp;
	}

	/**
	 * get_upload_status
	 * 
	 * @param string $user
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function get_upload_status($user)
	{
		$this->auth('read')->api_call('vimeo.people.getUploadStatus', array('user' => $user));
		return $this->reponse->user;
	}

	/**
	 * add_suscription
	 * 
	 * @param string $user
	 * @param string $type
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function add_subscription($user, $type)
	{
		$params = array
		(
			'user'	=> $user,
			'type'	=> $type
		);
		
		$this->auth('write')->api_call('vimeo.people.addSubscription', $params, true);
		return $this->reponse->rsp;
	}

	/**
	 * remove_subscription
	 * 
	 * @param string $user
	 * @param string $type
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function remove_subscription($user, $type)
	{
		$params = array
		(
			'user'	=> $user,
			'type'	=> $type
		);
		
		$this->auth('write')->api_call('vimeo.people.removeSubscription', $params, true);
		return $this->reponse->rsp;
	}

	/**
	 * get_contacts_list
	 * 
	 * @param string $user_id
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function get_contacts_list($user_id)
	{
		$this->api_call('vimeo.contacts.getList', array('user_id' => $user_id));
		return $this->response->contact;
	}

	/**
	 * get_upload_ticket
	 * 
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function get_upload_ticket()
	{
		$this->auth('write')->api_call('vimeo.videos.getUploadTicket');
		return $this->response->ticket->id;
	}

	/**
	 * check_upload_status
	 * 
	 * @param string $ticket_id
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function check_upload_status($ticket_id)
	{
		$this->auth('write')->api_call('vimeo.videos.checkUploadStatus', array('ticket_id' => $ticket_id));
		return $this->response->ticket;
	}

	/**
	 * upload
	 * 
	 * @param string $video
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function upload($video)
	{
		if ( ! file_exists($video) or ! is_readable($video))
			throw new Kohana_User_Exception('Vimeo Driver', Kohana::lang('service.file_error', $video));

		$params['api_key'] = $this->api_key;
		$params['ticket_id'] = $this->get_upload_ticket();
		$params['auth_token'] = $this->token;
		$params['api_sig'] = $this->sign_params($this->secret . $params);
		$params['video'] = '@' . $video;
		$this->api_url = 'http://www.vimeo.com/services/upload/';

		$this->auth('write')->api_call('', $params, true);
		return $this->response->rsp;
	}

	/**
	 * auth_check_token
	 * 
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function auth_check_token()
	{
		$params = array();
		if ($token = $this->auth_get_token() and $token !== '')
			$params = array('token' => $token);

		$this->api_call('vimeo.auth.checkToken', $params);
		return $this->response->auth;
	}

	/**
	 * auth_get_frob
	 * 
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function auth_get_frob()
	{
		$this->api_call('vimeo.auth.getFrob');
		return (string) $this->response->frob;
	}

	/**
	 * auth_get_token
	 * 
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function auth_get_token()
	{
		if ( ! $frob = input::instance()->get('frob'))
			return false;

		$this->api_call('vimeo.auth.getToken', array('frob' => $frob));
		Session::instance()->set('vimeo_auth_token', (string) $this->response->auth->token);

		return Session::instance()->get('vimeo_auth_token');
	}

	/**
	 * auth
	 * 
	 * @param string $perms
	 * @return object SimpleXMLElement Object
	 * @access public
	 * 
	 */
	public function auth($perms = "read")
	{
		if ( ! Session::instance()->get('vimeo_auth_token') and ! input::instance()->get('frob'))
		{
			url::redirect("http://www.vimeo.com/services/auth/?".self::sign_params($this->secret, array("api_key" => $this->api_key, "perms" => $perms)));
		}
		else
		{
			if ( ! $this->auth_check_token())
			{
				Session::instance()->delete('vimeo_auth_token');
				$this->auth($perms);
			}
		}
		
		return $this;
	}

	/**
	 * api_call
	 * 
	 * @param string $api_url
	 * @param array $params
	 * @param boolean $post
	 * @return void
	 * @access protected
	 * 
	 */
	protected function api_call($api_url, $params = array(), $post = false)
	{
		$params = array_merge(array('method' => $api_url, 'api_key' => $this->api_key), $params);

		if ($token = Session::instance()->get('vimeo_auth_token'))
			$params = array_merge($params, array('auth_token' => $token));

		if ( ! empty($this->secret))
			$params = self::sign_params($this->secret, $params);
		
		if ($post === true)
			$this->post();
	
		if ( ! $result = parent::api_call($params, false))
			throw new Kohana_User_Exception('Vimeo Driver', Kohana::lang('service.invalid_response', $this->last_api_call(), $this->last_status_code()));
		
		$xml = simplexml_load_string($result);
		
		if (false === $xml)
			throw new Kohana_User_Exception('Vimeo Driver', Kohana::lang('service.xml_parse_error'));
		
		if ( (string) $xml['stat'] !== 'ok')
			throw new Kohana_User_Exception('Vimeo Driver', Kohana::lang('service.response_error', (string) $xml->err['msg'], $this->lastapi_call()));
		
		$this->response = $xml;
	}

	/**
	 * sign_params
	 * 
	 * @param string $secret
	 * @param array $args
	 * @return string
	 * @access protected
	 * 
	 */
	protected static function sign_params($secret, $args)
	{
		$a = '';
		$v = array();
		ksort($args);

		foreach($args as $k => $val)
		{
			$a .= $k . $val;
			$v[] = $k . '=' . urlencode($val);
		}
		$v[] = 'api_sig=' . md5($secret . $a);

		return implode('&', $v);
	}

} //End Vimeo Driver